package com.virus.mall.service.impl;

import com.sun.org.apache.regexp.internal.RE;
import com.virus.mall.dao.GoodsDao;
import com.virus.mall.dao.UserDao;
import com.virus.mall.model.*;
import com.virus.mall.model.bo.*;
import com.virus.mall.model.vo.*;
import com.virus.mall.service.GoodsService;
import com.virus.mall.utils.MybatisUtils;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.ibatis.session.SqlSession;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

/**
 * @Classname GoodsServiceImpl
 * @Description 商品模块业务层实现类
 * @Date 2021/4/16 22:50
 * @Created by virus
 */
public class GoodsServiceImpl implements GoodsService {

    /**
     * 获得商品类型信息
     *
     * @return typeList
     */
    public List<Type> getType() {
        SqlSession session = MybatisUtils.getSession();
        GoodsDao mapper = session.getMapper(GoodsDao.class);
        List<Type> typeList = mapper.getType();
        MybatisUtils.releaseSession(session);
        return typeList;
    }

    /**
     * 根据商品类型分类获得商品信息
     *
     * @param typeId
     * @return goodsGetByTypeVoList
     */
    public List<GoodsGetByTypeVo> getGoodsByType(Integer typeId) {
        SqlSession session = MybatisUtils.getSession();
        GoodsDao mapper = session.getMapper(GoodsDao.class);
        List<GoodsGetByTypeVo> goodsGetByTypeVoList = mapper.getGoodsByType(typeId);
        MybatisUtils.releaseSession(session);
        return goodsGetByTypeVoList;
    }

    public boolean addGoods(AddGoodsBo addGoodsBo) {
        List<Spec> specList = addGoodsBo.getSpecList();
        Integer stockNum = specList.get(0).getStockNum();
        Double price = specList.get(0).getUnitPrice();
        for (Spec spec : specList) {
            if (spec.getStockNum() > stockNum) {
                stockNum = spec.getStockNum();
            }
            if (spec.getUnitPrice() < price) {
                price = spec.getUnitPrice();
            }
        }
        SqlSession session = MybatisUtils.getSession();
        GoodsDao mapper = session.getMapper(GoodsDao.class);
        try {
            Goods goods = new Goods(null, addGoodsBo.getImg(), addGoodsBo.getName(), price, addGoodsBo.getTypeId(), stockNum, addGoodsBo.getDesc());
            goods.setHasDomain(false);
            Integer affectedGoodsRow = mapper.addGoods(goods);
            if (affectedGoodsRow <= 0) {
                return false;
            }
            ArrayList<Spec> specs = new ArrayList<Spec>();
            for (Spec s : specList) {
                Spec spec = new Spec(null, s.getSpecName(), s.getStockNum(), s.getUnitPrice(), goods.getId());
                specs.add(spec);
            }
            Integer affectedSpecRow = mapper.addSpecList(specs);
            if (affectedSpecRow <= 0) {
                return false;
            }
            session.commit();
        } catch (Exception e) {
            e.printStackTrace();
            session.rollback();
            return false;
        } finally {
            session.close();
        }
        return true;
    }

    public boolean deleteGoods(Integer id) {
        SqlSession session = MybatisUtils.getSession();
        GoodsDao mapper = session.getMapper(GoodsDao.class);
        try {
            Integer affectedGoodsRow = mapper.deleteGoods(id);
            if (affectedGoodsRow <= 0) {
                return false;
            }
            Integer affectedSpecRow = mapper.deleteSpecByGoodsId(id);
            if (affectedSpecRow <= 0) {
                return false;
            }
            session.commit();
        } catch (Exception e) {
            e.printStackTrace();
            session.rollback();
            return false;
        } finally {
            session.close();
        }
        return true;
    }

    public boolean addType(AddTypeBo addTypeBo) {
        SqlSession session = MybatisUtils.getSession();
        GoodsDao mapper = session.getMapper(GoodsDao.class);
        Type type = new Type(null, addTypeBo.getName());
        Integer affectedRow = mapper.addType(type);
        MybatisUtils.releaseSession(session);
        return affectedRow > 0;
    }

    public boolean deleteType(Integer typeId) {
        SqlSession session = MybatisUtils.getSession();
        GoodsDao mapper = session.getMapper(GoodsDao.class);
        try {
            Integer affectedTypeRow = mapper.deleteType(typeId);
            if (affectedTypeRow <= 0) {
                return false;
            }
            List<Integer> goodsIdList = mapper.selectGoodsIdByTypeId(typeId);
            Integer affectedGoodsRow = mapper.deleteGoodsByTypeId(typeId);
            if (goodsIdList.size() > 0) {
                Integer affectedSpecRow = mapper.deleteSpecByIdList(goodsIdList);
                if (affectedGoodsRow > 0 && affectedSpecRow <= 0) {
                    return false;
                }
            }
            session.commit();
        } catch (Exception e) {
            e.printStackTrace();
            session.rollback();
            return false;
        } finally {
            session.close();
        }
        return true;
    }

    public GoodsGetInfoVo getGoodsInfo(Integer id) {
        SqlSession session = MybatisUtils.getSession();
        GoodsDao mapper = session.getMapper(GoodsDao.class);
        Goods goods = mapper.getGoodsInfo(id);
        goods.setHasDomain(false);
        GoodsGetVo goodsGetVo = new GoodsGetVo(goods.getId(), goods.getImg(), goods.getName(), goods.getDescription(), goods.getTypeId(), goods.getPrice());
        goodsGetVo.setHasDomain(false);
        ArrayList<SpecGetVo> specGetVos = new ArrayList<SpecGetVo>();
        for (Spec spec : goods.getSpecs()) {
            specGetVos.add(new SpecGetVo(spec.getId(), spec.getSpecName(), spec.getStockNum(), spec.getUnitPrice()));
        }
        GoodsGetInfoVo goodsGetInfoVo = new GoodsGetInfoVo(goodsGetVo, specGetVos);
        MybatisUtils.releaseSession(session);
        return goodsGetInfoVo;
    }

    public AddSpecVo addSpec(AddSpecBo addSpecBo) {
        SqlSession session = MybatisUtils.getSession();
        GoodsDao mapper = session.getMapper(GoodsDao.class);
        Spec spec = new Spec(null, addSpecBo.getSpecName(), addSpecBo.getStockNum(), addSpecBo.getUnitPrice(), addSpecBo.getGoodsId());
        AddSpecVo addSpecVo = null;
        try {
            Integer count = mapper.judgeSpecDuplicate(addSpecBo.getGoodsId(), addSpecBo.getSpecName());
            if (count > 0) {
                return null;
            }
            addSpecVo = new AddSpecVo(spec.getGoodsId(), spec.getSpecName(), spec.getStockNum(), spec.getUnitPrice());
            session.commit();
        } catch (Exception e) {
            e.printStackTrace();
            session.rollback();
            return null;
        } finally {
            session.close();
        }
        return addSpecVo;
    }

    public boolean deleteSpec(SpecDeleteBo specDeleteBo) {
        SqlSession session = MybatisUtils.getSession();
        GoodsDao mapper = session.getMapper(GoodsDao.class);
        Spec spec = new Spec(null, specDeleteBo.getSpecName(), null, null, specDeleteBo.getGoodsId());
        Integer affectedRow = mapper.deleteSpec(spec);
        MybatisUtils.releaseSession(session);
        return affectedRow > 0;
    }

    public boolean updateGoods(GoodsUpdateBo goodsUpdateBo) {
        SqlSession session = MybatisUtils.getSession();
        GoodsDao mapper = session.getMapper(GoodsDao.class);
        Goods goods = new Goods(goodsUpdateBo.getId(), goodsUpdateBo.getImg(), goodsUpdateBo.getName(), null
                , goodsUpdateBo.getTypeId(), null, goodsUpdateBo.getDesc());
        goods.setHasDomain(false);
        ArrayList<Spec> specs = new ArrayList<Spec>();
        boolean flag = false;
        for (SpecGetVo specGetVo : goodsUpdateBo.getSpecList()) {
            Spec spec = new Spec(specGetVo.getId(), specGetVo.getSpecName(), specGetVo.getStockNum(), specGetVo.getUnitPrice(), specGetVo.getGoodsId());
            if (specGetVo.getId() == null) {
                flag = true;
            }
            specs.add(spec);
        }
        try {
            Integer affectedGoodsRow = mapper.updateGoods(goods);
            if (affectedGoodsRow <= 0) {
                return false;
            }
            Integer affectedSpecRow = mapper.updateSpec(specs);
            Integer affectedAddSpecRow = 0;
            if (flag) {
                affectedAddSpecRow = mapper.addSpecList(specs);
            }
            if (affectedAddSpecRow + affectedSpecRow <= 0) {
                return false;
            }
            session.commit();
        } catch (Exception e) {
            e.printStackTrace();
            session.rollback();
            return false;
        } finally {
            session.close();
        }
        return true;
    }

    public List<Reply> noReplyMsg() {
        SqlSession session = MybatisUtils.getSession();
        GoodsDao mapper = session.getMapper(GoodsDao.class);
        List<Reply> replies = mapper.noReplyMsg();
        MybatisUtils.releaseSession(session);
        return replies;
    }

    public List<Reply> repliedMsg() {
        SqlSession session = MybatisUtils.getSession();
        GoodsDao mapper = session.getMapper(GoodsDao.class);
        List<Reply> replies = mapper.repliedMsg();
        MybatisUtils.releaseSession(session);
        return replies;
    }

    public boolean reply(ReplyBo replyBo) {
        SqlSession session = MybatisUtils.getSession();
        GoodsDao mapper = session.getMapper(GoodsDao.class);
        Reply reply = new Reply(replyBo.getId(), replyBo.getContent());
        Integer affectedRow = mapper.reply(reply);
        MybatisUtils.releaseSession(session);
        return affectedRow > 0;
    }

    public GoodsGetInfoMallVo getMallGoodsInfo(Integer id) {
        SqlSession session = MybatisUtils.getSession();
        GoodsDao mapper = session.getMapper(GoodsDao.class);
        Goods goods = mapper.getGoodsInfo(id);
        if (goods == null) {
            return null;
        }
        goods.setHasDomain(false);
        ArrayList<SpecGetVo> specGetVos = new ArrayList<SpecGetVo>();
        for (Spec spec : goods.getSpecs()) {
            SpecGetVo specGetVo = new SpecGetVo(spec.getId(), spec.getSpecName(), spec.getStockNum(), spec.getUnitPrice());
            specGetVos.add(specGetVo);
        }
        GoodsGetInfoMallVo goodsGetInfoMallVo = new GoodsGetInfoMallVo();
        goodsGetInfoMallVo.setSpecs(specGetVos);
        goodsGetInfoMallVo.setImg(goods.getImg());
        goodsGetInfoMallVo.setName(goods.getName());
        goodsGetInfoMallVo.setDesc(goods.getDescription());
        goodsGetInfoMallVo.setTypeId(goods.getTypeId());
        MybatisUtils.releaseSession(session);
        return goodsGetInfoMallVo;
    }

    public List<GetGoodsMsgVo> getGoodsMsg(Integer id) {
        SqlSession session = MybatisUtils.getSession();
        GoodsDao mapper = session.getMapper(GoodsDao.class);
        List<Reply> replies = mapper.getGoodsMsg(id);
        ArrayList<GetGoodsMsgVo> getGoodsMsgVos = new ArrayList<GetGoodsMsgVo>();
        for (Reply reply : replies) {
            GetGoodsMsgVo getGoodsMsgVo = new GetGoodsMsgVo(id, reply.getContent(), reply.getUser().getNickname()
                    , reply.getCreatetime(), new ReplyVo(reply.getReplyContent(), reply.getUpdatetime()));
            getGoodsMsgVos.add(getGoodsMsgVo);
        }
        MybatisUtils.releaseSession(session);
        return getGoodsMsgVos;
    }

    public boolean askGoodsMsg(AskGoodsMsgBo askGoodsMsgBo) {
        SqlSession session = MybatisUtils.getSession();
        GoodsDao goodsMapper = session.getMapper(GoodsDao.class);
        UserDao userMapper = session.getMapper(UserDao.class);
        try {
            Integer userId = userMapper.selectIdByEmail(askGoodsMsgBo.getToken());
            String nickname = userMapper.selectNicknameByUserId(userId);
            String goodsName = goodsMapper.selectGoodsNameById(askGoodsMsgBo.getGoodsId());
            Reply reply = new Reply();
            reply.setUser(new UserVo());
            reply.setGoods(new Goods());
            reply.setUsername(nickname);
            reply.setContent(askGoodsMsgBo.getMsg());
            reply.setGoodsId(askGoodsMsgBo.getGoodsId());
            reply.setUserId(userId);
            reply.setGoodsName(goodsName);
            Integer affectedRow = goodsMapper.askGoodsMsg(reply);
            if (affectedRow <= 0) {
                return false;
            }
            session.commit();
        } catch (Exception e) {
            e.printStackTrace();
            session.rollback();
            return false;
        } finally {
            session.close();
        }
        return true;
    }

    public List<SearchGoodsVo> searchGoods(String keyword) {
        SqlSession session = MybatisUtils.getSession();
        GoodsDao mapper = session.getMapper(GoodsDao.class);
        List<SearchGoodsVo> searchGoods = mapper.searchGoods(keyword);
        MybatisUtils.releaseSession(session);
        return searchGoods;
    }

    public GetGoodsCommentVo getGoodsComment(Integer goodsId) {
        SqlSession session = MybatisUtils.getSession();
        GoodsDao mapper = session.getMapper(GoodsDao.class);
        GetGoodsCommentVo getGoodsCommentVo = null;
        try {
            List<Comments> commentsList = mapper.selectComments(goodsId);
            Integer count = mapper.selectCountByGoodsId(goodsId);
            Integer fullCount = mapper.selectFullByGoodsId(goodsId);
            double rate = (double) fullCount / (double) count;
            getGoodsCommentVo = new GetGoodsCommentVo(commentsList, rate * 100);
            session.commit();
        } catch (Exception e) {
            e.printStackTrace();
            session.rollback();
            return null;
        } finally {
            session.close();
        }
        return getGoodsCommentVo;
    }
}
